<?php

/**
 * Базовый класс формы восстановления забытого пароля — для пользователя и для
 * админа.
 *
 */
abstract class Security_Action_Forgot extends Kernel_Action_Form {

    /**
     * Роль, которой должен принадлежать пользователь, чтобы восстановить пароль
     * через данную форму.
     *
     * @var integer
     */
    protected $_role;

    /**
     * Путь к файлу шаблона страницы с сообщением о том, что форма сохранена.
     * Если не указан, форма просто будет перерисована.
     *
     * @var string
     */
    protected $_template_saved = 'blank.tpl';

    /**
     * Флаг, указывающий, что после сохранения данных формы не нужно показывать
     * сответствующее сообщение.
     *
     * @var boolean
     */
    protected $_no_message = true;

    /**
     * Костыль это.
     *
     * @var boolean
     */
    private $_saved = false;

    /**
     * Инициализирует элементы формы.
     *
     */
    protected function _initElements() {
        $this->_addElement('email', 'string', array(
            'required' => true,
            'validators' => array(
                array('Security_Validator_Forgot', array('role' => $this->_role))
            ),
            'value' => Application::getRequest()->get('email'),
        ));
    }

    /**
     * Сохраняет данные формы. Генерирует хэш и отправляет пользователю почтовое
     * сообщение.
     *
     */
    protected function _save()
    {
        $email = $this->_getValue('email');

        // определяем из конфигурации системы, используются ли секретные вопросы,
        // и определены ли они для этого пользователя - чтоб не было проблем при
        // изменении конфигурации в ходе работы проекта, потом подробнее опишу
        if ($this->_hasQuestions($email)) {

            // :KLUDGE: morozov 17092007: вгрязную снимаем шаблон сохраненной
            // страницы, т.к. компонент второго шага формы должен выставить свой
            $this->_template_saved = null;
            $this->_forward(new Security_Action_Forgot_Step2);
        } else {

            // генерируем хэш для аккаунта с указанным email
            $hash = Confirm::create(Security_Utils_Subject::getSubjectByEmail($email), 'security', 'reset');

            // определяем идентификатор профайла, данные из которого нужно
            // подставить в почтовое сообщение
            $profile = $this->_getProfileId($email);

            // отправляем пользователю письмо
            $this->_send($profile, $hash);
        }

        $this->_saved = true;
    }

    /**
     * Выводит данные формы в шаблон.
     *
     */
    protected function _draw()
    {
        if (!$this->_saved)
        {
            parent::_draw();
        }
    }

    /**
     * Отправляет сообщение указанному пользователю.
     *
     * @param   integer $profile
     * @param   string  $hash
     * @return  boolean
     */
    abstract protected function _send($profile, $hash);

    /**
     * Возвращает секретные указанного субъекта безопасности.
     *
     * @param   integer  $subject
     * @return  array
     */
    private function _getQuestions($subject)
    {
        return Security_Utils_Subject::getQuestions($subject);
    }

    /**
     * Возвращает идентификатор профайла с указанным email.
     *
     * @param   string  $email
     * @return  integer
     */
    private function _getProfileId($email)
    {
        return Security_Utils_Subject::getProfileId($email, $this->_role);
    }

    /**
     * Определяет, указаны ли секретные вопросы для аккаунта с указанным e-mail.
     *
     * @param   string  $email
     * @return  boolean
     */
    private function _hasQuestions($email)
    {
        return Kernel_Config::get('security', 'questions') > 0
            && Security_Utils_Subject::hasQuestions($email);
    }
}
